package owg.util.editor2d;


import java.awt.AWTEvent;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.AWTEventListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;

import javax.swing.JComboBox;
import javax.swing.text.JTextComponent;

import owg.util.euclidian.V2D;

public class Editor2DEventHandler implements AWTEventListener, MouseListener, MouseMotionListener, MouseWheelListener {
	
	public final Editor2D editor;
	
	public Editor2DEventHandler(Editor2D editor) {
		this.editor = editor;
		editor.mainPanel.addMouseListener(this);
		editor.mainPanel.addMouseWheelListener(this);
		editor.mainPanel.addMouseMotionListener(this);
		Toolkit.getDefaultToolkit().addAWTEventListener(this, AWTEvent.KEY_EVENT_MASK);
	}
	
	public void destroy()
	{
		editor.mainPanel.removeMouseListener(this);
		editor.mainPanel.removeMouseWheelListener(this);
		editor.mainPanel.removeMouseMotionListener(this);
		Toolkit.getDefaultToolkit().removeAWTEventListener(this);
	}
	
	
	@Override
	public void eventDispatched(AWTEvent event) {
		KeyEvent evt = (KeyEvent) event;
		if(evt.getSource() instanceof JTextComponent || evt.getSource() instanceof JComboBox<?>)
			return;
		editor.enqueue(evt);
	}
	
	@Override
	public void mouseWheelMoved(MouseWheelEvent e)
	{
		editor.enqueue(e);
	}
	@Override
	public void mouseClicked(MouseEvent e) {
		editor.enqueue(e);
	}
	
	@Override
	public void mouseEntered(MouseEvent e) {
		editor.enqueue(e);
	}
	
	@Override
	public void mouseExited(MouseEvent e) {
		editor.enqueue(e);
	}
	
	@Override
	public void mousePressed(MouseEvent e) {
		editor.enqueue(e);
	}
	
	@Override
	public void mouseReleased(MouseEvent e) {
		editor.enqueue(e);
	}
	
	public V2D getMousePosition()
	{
		Point p = MouseInfo.getPointerInfo().getLocation();
		Point lost = editor.mainPanel.getLocationOnScreen();
		p.x -= lost.x;
		p.y -= lost.y;
		return editor.camera.normToWorld((float)p.x/editor.mainPanel.getWidth(), (float)p.y/editor.mainPanel.getHeight());
	}
	
	public V2D getSnappedMouse() {
		return correctToGrid(getMousePosition());
	}
	/**Modify the input vector to be snapped to the current grid.
	 * The vector is unmodified if snapping is not enabled.
	 * @return the input vector.*/
	public V2D correctToGrid(V2D position)
	{
		return correctToGrid(position, editor.settings.nwSnap.get());
	}
	/**Modify the input vector to be snapped to the current grid.
	 * The vector is unmodified if snapping is not enabled.
	 * @param nwSnap whether to use round-down snapping
	 * @return the input vector.*/
	public V2D correctToGrid(V2D position, boolean nwSnap)
	{
		if(editor.settings.snapEnabled.get())
		{
			int snap;
			snap = editor.settings.snapWidth.get();
			if(snap > 0)
				position.p[0] = correctToGrid(position.p[0], snap, nwSnap);
			snap = editor.settings.snapHeight.get();
			if(snap > 0)
				position.p[1] = correctToGrid(position.p[1], snap, nwSnap);
		}
		if(editor.settings.snapInteger.get())
		{
			position.p[0] = Math.floor(position.p[0]);
			position.p[1] = Math.floor(position.p[1]);
		}   
		return position;
	}
	
	public double correctToGrid(double d, int grid, boolean roundDown)
	{
		if(roundDown)
			return Math.floor(d / grid) * grid;
		else
			return Math.round(d / grid) * grid;
	}
	
	@Override
	public void mouseDragged(MouseEvent e) {
		editor.enqueue(e);
	}
	
	@Override
	public void mouseMoved(MouseEvent e) {
		editor.enqueue(e);
	}
	
}
